from google.appengine.ext import db
import random
import urllib

class Job(db.Expando):
  """ Instructions to do something
  
  AppEngine restrictions require us to do some batch jobs on other boxes
  that have remote access to the datastore. Passing the actual job details
  through a redirect is risky since the end-user can now see everything
  Much safer to store things here
  
  Most of the batch object is in the batch directory. This model is here
  only because it contains the datastore model that AppEngine uses to
  communicate with the batch worker.
  
  """
  # Handler is the name of the function that interprets job
  handler = db.StringProperty()
  
  def redirect_link(self):
    """ Returns link that we can redirect the user to that will do this job """
    worker = Worker.get_random()
    return worker.address + '?' + urllib.urlencode({'key' : str(self.key())})

class Worker(db.Model):
  """ The address of an external box that can do a batch job """
  address = db.LinkProperty()
  
  @classmethod
  def get_random(cls):
    """ Return a random token -- randomness permits equal sharding """
    workers = cls.all().fetch(1000)
    return workers[random.randint(0, len(workers) - 1)]
  
  @classmethod
  def register(cls, address):
    """ Called by new external boxes to register with AppEngine """
    if not address.startswith('http'):
      address = 'http://' + address
    return cls.get_or_insert(key_name=address, address=address)
